package com.lanyou.esb.cook.proxy.redis;

import java.util.Random;

import redis.clients.jedis.Jedis;

/**
 * redis锁
 * 
 * @author Davey.wu
 */
public class RedisLock {
	/** 加锁标志 */
	public static final String LOCKED = "TRUE";

	/** 毫秒与毫微秒的换算单位 1毫秒 = 1000000毫微秒 */
	public static final long MILLI_NANO_CONVERSION = 1000 * 1000L;

	/** 默认超时时间（毫秒） */
	public static final long DEFAULT_TIME_OUT = 10000;

	public static final Random RANDOM = new Random();

	/** 锁的超时时间（秒），过期删除 */
	public static final int EXPIRE = 3 * 60;

	/**
	 * 加锁
	 * 
	 * @param jedis
	 * @param key
	 *            ：键
	 * @param timeout
	 *            ：超时时间
	 * @return
	 */
	public static boolean lock(Jedis jedis, String key, long timeout) {
		long nano = System.nanoTime();
		key = key.concat("_lock");
		timeout *= MILLI_NANO_CONVERSION;
		try {
			while ((System.nanoTime() - nano) < timeout) {
				if (jedis.setnx(key, LOCKED) == 1) {
					jedis.expire(key, EXPIRE);
					return true;
				}
				// 短暂休眠，避免出现活锁
				Thread.sleep(3, RANDOM.nextInt(500));
			}
		} catch (Exception e) {
			throw new RuntimeException("Locking error", e);
		}
		return false;
	}

	/**
	 * 加锁
	 * 
	 * @param jedis
	 * @param key
	 *            ：键
	 * @param timeout
	 *            ：超时时间
	 * @param expire
	 *            ：锁的超时时间（秒），过期删除
	 * @return
	 */
	public static boolean lock(Jedis jedis, String key, long timeout, int expire) {
		key = key.concat("_lock");
		long nano = System.nanoTime();
		timeout *= MILLI_NANO_CONVERSION;
		try {
			while ((System.nanoTime() - nano) < timeout) {
				if (jedis.setnx(key, LOCKED) == 1) {
					jedis.expire(key, expire);
					return true;
				}
				// 短暂休眠，避免出现活锁
				Thread.sleep(3, RANDOM.nextInt(500));
			}
		} catch (Exception e) {
			throw new RuntimeException("Locking error", e);
		}
		return false;
	}

	/**
	 * 释放锁
	 * 
	 * @param jedis
	 * @param key
	 */
	public static void unlock(Jedis jedis, String key) {
		key = key.concat("_lock");
		try {
			jedis.del(key);
		} finally {

		}
	}

}
